#ifndef VARIABLE_UNIFIER_H_
#define VARIABLE_UNIFIER_H_

#include <map>
#include <string>	

namespace combo {

enum UnifierOperation {
	UNIFY_NOT,
	UNIFY_AND,
	UNIFY_OR
	
};

// Map used to hold the variables and its states (true or false)
typedef std::map<std::string, bool> UnifierMap;

// Map iterator
typedef std::map<std::string, bool>::iterator UnifierIt;

// Map const_itertator
typedef std::map<std::string, bool>::const_iterator UnifierConstIt;

class variable_unifier {
	
	public:
		
		/**
		 * Special variable_unifier
		 */
		static variable_unifier& DEFAULT_VU();
		
		/**
		 * Constructors
		 */
		variable_unifier();
		variable_unifier(const variable_unifier& unifier);
		
		/**
		 * Destructor
		 */
		virtual ~variable_unifier();
		
		/**
		 * Unifiy this variable_unifier object with the parameter unifier informed
		 * 
		 * @param unifier The variable_unifier that should be unified with this object. 
		 */
		void unify(combo::UnifierOperation operation, variable_unifier& unifier);
		
		/**
		 * Get the UnifierMap
		 * 
		 * @return The unifier map
		 */
		 const UnifierMap& getMap() const;
		
         /**
          * Return an iterator that points to the beginig of the UnifierMap.
          */
         UnifierIt getMapBeginIterator();
         
         /**
          * Return an iterator that points to the ending of the UnifierMap.
          */
         UnifierIt getMapEndIterator();
		 
         /**
          * Get the variable state from UnifierMap.
          *
          * @param variable The variable name
          * @retun The variable state for the given variable. If variable
          * not present in UnifierMap, false is returned.
          */ 
		 bool getVariableState(std::string& variable);

         /**
          * Set the variable statee in the UnifiedMap
          *
          * @param variable The variable name.
          * @param state The variable state.
          */
         void setVariableState(std::string& variable, bool state);

		/**
		 * Insert a variable into unifier map. If an entry with the  
		 * 
		 * @param name The variable's name
		 * @param state The variable's state (true default)
		 */
		void insert(const std::string& variable, const bool state = true);

        /**
         * Inform if a given variable is presente in the UnifierMap
         *
         * @param variable The variable name.
         * @return True if the variable is present in the UnifierMap, 
         * false otherwise.
         */ 
        bool contains(const std::string& variable) const;
        
        /**
         * Get the UnifiedMap size
         */
        int mapSize() const;

		/**
		 * Inform if the variable_unifier element is empty
		 */
		inline bool isEmpty() const { 
			return this->umap.empty(); 
		}
		
		/**
		 * Inform if there is at least one variable in UnifierMap that has its
		 * state set to true.
		 */
		inline bool isOneVariableActive() const {
			return this->oneVariableActive;
		}
		
		/**
		 * Set oneVariableActive field
		 */
		inline void setOneVaribleActive(bool state){
			this->oneVariableActive = state;
		}
		
	private:
		
		/**
		 * The map holding the variables to be unified and their states
		 */
		UnifierMap umap;
		
		/**
		 * Inform if there is at least one variable in UnifierMap that has its
		 * state set to true.
		 */
		bool oneVariableActive;
			
}; // class
}  // namespace combo

#endif /*VARIABLE_UNIFIER_H_*/
